using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Random = UnityEngine.Random;


public class GamePanel : MonoBehaviour
{
    public GameOverPanel gameOverPanel;
    enum MoveActionType
    {
        Up,Down,Right,Left
    }
    //游戏事件
    public event Action GameoverEvent;
    public event Action<int> ScoreAddEvent;
    
    //生成 2的概率， 只会随机的生成2或者4
    public float probSpawnForTwo = 0.72f;
    

    //Grid 间距 
    public int gridSpacing = 5;
    public int gridPadding = 10;
    
    
    private Text textCurScore;
    private Text textBestScore;
    private int curScore;
    private int bestScore;
    

    //游戏数据
    private RectTransform rectTrancefromGrid;
    private int colCount;//格子列数 （行数==列数）
    private Item[,] items;//格子的引用


    private void Start()
    {
        InitCommpoment();
        InitGrid();
        GameoverEvent += onGameOver;
        ScoreAddEvent += onAddScore;
    }
    private void Update()
    {
        #region 输入
        if (Input.GetMouseButtonDown(0))
            OnMouseDown();
        if(Input.GetMouseButtonUp(0))
            OnMouseUp();
        if(Input.GetKeyDown(KeyCode.UpArrow))
            MoveAllItem(MoveActionType.Up);
        if(Input.GetKeyDown(KeyCode.DownArrow))
            MoveAllItem(MoveActionType.Down);
        if(Input.GetKeyDown(KeyCode.RightArrow))
            MoveAllItem(MoveActionType.Right);
        if(Input.GetKeyDown(KeyCode.LeftArrow))
            MoveAllItem(MoveActionType.Left);
        #endregion
    }
    
    #region 初始化
    //获取场景中的组件
    private void InitCommpoment()
    {
        rectTrancefromGrid = transform.Find("grid") as RectTransform;
        textCurScore = transform.Find("menu/scores/current/value_text").GetComponent<Text>();
        textBestScore = transform.Find("menu/scores/best/value_text").GetComponent<Text>();

        bestScore = PlayerPrefs.GetInt(Const.besetScore, 0);
        curScore = 0;
        textCurScore.text = "0";
        textBestScore.text = bestScore.ToString();
    }
    //初始化 格子
    private void InitGrid()
    {
        colCount = GlobalData.GetInt(Const.gameModel, 6);
        //设置格子 外观
        GridLayoutGroup gridGroup = rectTrancefromGrid.GetComponent<GridLayoutGroup>();
        gridGroup.padding = new RectOffset(gridPadding, gridPadding, gridPadding, gridPadding);
        gridGroup.spacing = new Vector2(gridSpacing, gridSpacing);
        float size = (rectTrancefromGrid.rect.width - gridPadding * 2) /colCount - gridSpacing;
        gridGroup.constraintCount = colCount;
        gridGroup.cellSize = new Vector2(size, size);
        //生成Item
        items = new Item[colCount, colCount];
        for (int i = 0; i < colCount; ++i)
        for (int j = 0; j < colCount; ++j)
        {
            var t = Item.SpawnItem(rectTrancefromGrid);
            items[i, j] = t;
        }
        //随机生成一个数值
        RandomSpawnNumber();
    }
    #endregion

    #region 输入
    private Vector3 mouseDownPos;
    private void OnMouseDown()
    {
        mouseDownPos = Input.mousePosition;
    }
    private void OnMouseUp()
    {
        var d = Input.mousePosition - mouseDownPos;
        if ( d.magnitude > 100.0f)
        {
            MoveActionType type;
            if (Mathf.Abs( d.x) > Mathf.Abs(d.y))
            {
                //水平变化
                if (d.x > 0)
                    type = MoveActionType.Left;
                else
                    type = MoveActionType.Right;
            }
            else
            {
                //垂直变化
                if (d.y > 0)
                    type = MoveActionType.Up;
                else
                    type = MoveActionType.Down;
            }
            MoveAllItem(type);
        }
    }
    #endregion
    
    
    //随机生成数字
    private void RandomSpawnNumber()
    {
        //查找当前所有没有数值的Item
        List<Item> notHasNumItems = new List<Item>();
        foreach (var it in items)
        {
            if(!it.hasNumber())
                notHasNumItems.Add(it);
        }
        if (notHasNumItems.Count == 0)
        {
            CheckGameIsOver();
            return;
        }

        if (canSpawnNum)
        {
            int r = Random.Range(0, notHasNumItems.Count);
            Item item = notHasNumItems[r];
    
            int randomVal = 2 ;
            if (Random.Range(0, 1) > probSpawnForTwo)
                randomVal = 4;
            item.SetNumItem(NumItem.SpawnNumber(item.transform,randomVal));
        }
    }
    //检查游戏是否结束 ， 数字满了才会检查
    private void CheckGameIsOver()
    {
        bool isNotGameOver = false;
        for (int i = 1; i < colCount; i+=2)
        {
            for (int j = 1; j < colCount; j += 2)
            {
                int val = items[i, j].numItem.number;
                //上
                int temp = i - 1;
                if (temp >=0&&items[temp, j].numItem.number == val)
                {
                    isNotGameOver = true;
                    break;
                }
                //下
                temp = i + 1;
                if (temp < colCount&&items[temp, j].numItem.number == val)
                {
                    isNotGameOver = true;
                    break;
                }
                //右
                temp = i + 1;
                if (temp < colCount&&items[i, temp].numItem.number == val)
                {
                    isNotGameOver = true;
                    break;
                }
                //左
                temp = i - 1;
                if (temp > 0 &&items[i, temp].numItem.number == val)
                {
                    isNotGameOver = true;
                    break;
                }
            }
        }
        if (!isNotGameOver)
        {
            GameoverEvent?.Invoke();
        }
    }
    //移动数字
    private bool canSpawnNum = true;
    private void MoveAllItem(MoveActionType type)
    {
        canSpawnNum = false;
        switch (type)
        {
            case MoveActionType.Up:
                for (int i = 0; i < colCount; ++i)
                    ScanItems(0, i, colCount - 1, i);
                break;
            case MoveActionType.Down:
                for (int i = 0; i < colCount; ++i)
                    ScanItems(colCount - 1, i, 0, i);
                break;
            case MoveActionType.Right:
                for (int i = 0; i < colCount; ++i)
                    ScanItems(i, colCount-1, i, 0);
                break;
            case MoveActionType.Left:
                for (int i = 0; i < colCount; ++i)
                    ScanItems(i, 0, i, colCount-1);
                break;
        }
        //还原标记
        foreach (var it in items)
        {
            if (it.hasNumber())
            {
                it.numItem.notIsMergedNumber = true;
            }
        }
        RandomSpawnNumber();
        
            
    }
    //让路径上的元素 ，往起点处 合并/移动
    private void ScanItems(int beginX, int beginY, int endX, int endY)
    {
        int dx = beginX == endX ? 0 : (endX - beginX)/Math.Abs(endX - beginX);
        int dy = beginY == endY ? 0 : (endY - beginY)/Math.Abs(endY - beginY);

        int tBeginX = beginX ;
        int tBeginY = beginY ;
        while (!(tBeginX == endX && tBeginY == endY))
        {
            tBeginX  += dx;
            tBeginY  += dy;
            if (items[tBeginX, tBeginY].hasNumber())
                MoveItem(tBeginX, tBeginY, beginX, beginY);
        }
    }
    //begin Item一个格子一个格子的移动到end,会造成合并路径上的数字 . 起点必须有数值
    private void MoveItem(int beginX,int beginY, int endX,int endY)
    {
        int dx = beginX == endX ? 0 : (endX - beginX)/Math.Abs(endX - beginX);
        int dy = beginY == endY ? 0 : (endY - beginY)/Math.Abs(endY - beginY);
        while (!(beginX==endX&&beginY==endY))
        {
             Item it1 = items[beginX, beginY];
             beginX += dx;
             beginY += dy;
             Item it2 = items[beginX, beginY];
             if (it2.hasNumber())
             {
                 int val = it1.numItem.number;
                 if (it2.numItem.number == val && it2.numItem.notIsMergedNumber)
                 {
                     it1.MergeNum(it2);
                     ScoreAddEvent?.Invoke(val);//加分
                     canSpawnNum = true;
                 }
                 break;
             }
             else
             {
                 it1.MoveNumItem(it2);
                 canSpawnNum = true;
             }
        }
        
    }

    public void Restart()
    {
        canSpawnNum = true;
        curScore = 0;
        textCurScore.text = "0";
        foreach (var it in items)
        {
            if (it.hasNumber())
            {
                GameObject.Destroy(it.numItem.gameObject);
                it.SetNumItem(null);
            }
        }
        RandomSpawnNumber();
    }
    //按钮事件
    public void OnBackClick()
    {
        SceneManager.LoadScene(0);
    }
    private void onGameOver()
    {
       gameOverPanel.Show();
    }
    private void onAddScore(int d)
    {
        curScore += d;
        textCurScore.text = curScore.ToString();
        if (curScore >= bestScore)
        {
            bestScore = curScore;
            textBestScore.text = bestScore.ToString();
            PlayerPrefs.SetInt(Const.besetScore,bestScore);
        }
    }
}
